package com.jblog.common.util;

import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Attribute;
import org.jsoup.nodes.Attributes;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.parser.Tag;

public final class HtmlUtils {
    private HtmlUtils() {
    }
    /**
     * 截取字符串长字，保留HTML格式
     * 
     * @param s
     * @param len
     *            字符长度
     */
    public static String htmlCut(String s, int len, String append) {
        if (null == s) {
            return "params is null!";
        } else if(len < 0) {
            len = 1;
        } else if (s.length() <= len) {
            return s;
        } else if (len > s.length()) {
            len = s.length();
        }
        if (null == append) {
            append = "";
        }
        
        Document dirtyDocument = Jsoup.parse(s);
        Element source = dirtyDocument.body();
        Document clean = Document.createShell(dirtyDocument.baseUri());
        Element dest = clean.empty();
        truncateHTML(source, dest, len);
        
        String html = dest.outerHtml();
        if (html.length() < s.length()) {
            html += append;
        }
        return html;
    }

    /**
     * 使用Jsoup预览
     * 
     * @param source
     *            需要过滤的
     * @param dest
     *            过滤后的对象
     * @param len
     *            截取字符长度
     */
    private static void truncateHTML(Element source, Element dest, int len) {
        List<Node> sourceChildren = source.childNodes();
        for (Node sourceChild : sourceChildren) {
            if (sourceChild instanceof Element) {
                Element sourceEl = (Element) sourceChild;
                Element destChild = createSafeElement(sourceEl);
                int txt = dest.text().length();
                if (txt >= len) {
                    break;
                } else {
                    len = len - txt;
                }
                dest.appendChild(destChild);
                truncateHTML(sourceEl, destChild, len);
            } else if (sourceChild instanceof TextNode) {
                int destLeng = dest.text().length();
                if (destLeng >= len) {
                    break;
                }
                TextNode sourceText = (TextNode) sourceChild;
                int txtLeng = sourceText.getWholeText().length();
                if ((destLeng + txtLeng) > len) {
                    int tmp = len - destLeng;
                    String txt = sourceText.getWholeText().substring(0, tmp);
                    TextNode destText = new TextNode(txt, sourceChild.baseUri());
                    dest.appendChild(destText);
                    break;
                } else {
                    TextNode destText = new TextNode(sourceText.getWholeText(),
                            sourceChild.baseUri());
                    dest.appendChild(destText);
                }
            }
        }
    }

    /**
     * 按原Element重建一个新的Element
     * 
     * @param sourceEl
     * @return
     */
    private static Element createSafeElement(Element sourceEl) {
        String sourceTag = sourceEl.tagName();
        Attributes destAttrs = new Attributes();
        Element dest = new Element(Tag.valueOf(sourceTag), sourceEl.baseUri(),
                destAttrs);
        Attributes sourceAttrs = sourceEl.attributes();
        for (Attribute sourceAttr : sourceAttrs) {
            destAttrs.put(sourceAttr);
        }
        return dest;
    }
    
//    public static void main(String[] args) {
//        String html = "&nbsp;&nbsp;<p>测试</p><p>&nbsp;&nbsp;&nbsp;&nbsp;深圳居民<img />张先<font>生到香港购买</font></p>了一台iPad，但在返回深圳入境时，尽管其一再解释是自用物件，但仍需缴税后才能过关。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;■ 居民旅客携带20种不予免税的物品入境，需根据规定缴税。根据《海关总署公告2004年第7号》，iPad属于不免税物品，无论购买iPad的价格是否超过5000元，都应按照20%的税率缴税。<br />从事IT行业的深圳居民张先生到香港购买了一台iPad，在返回深圳入境时";
//        int len = 26;
//        System.out.println(HtmlUtils.truncateHTML(html, len));
//    }
}